﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;

namespace Results.Models
{
    /// <summary>
    /// Holds all the golf tournaments ever conducted
    /// </summary>
    public class TournamentsModel : List<TournamentModel>
    {
        /// <summary>
        /// Signal when the data is loaded
        /// </summary>
        public event EventHandler<TournamentsModelLoadedEventArgs> TournamentsModelLoaded;

        /// <summary>
        /// Fetch the data from the web
        /// </summary>
        /// <param name="path">Something like "http://www.premierjuniortour.com/results/"</param>
        public void Load(String path)
        {
            Load(new Uri(path + "Tournaments.txt"));
        }

        /// <summary>
        /// Start the asynch fetch
        /// </summary>
        /// <param name="uri"></param>
        /// <returns></returns>
        void Load(Uri uri)
        {
            try
            {
                _webClient = new WebClient();
                _webClient.OpenReadAsync(uri);
                _webClient.OpenReadCompleted += WebClientOpenReadCompleted;
            }
            catch (Exception e)
            {
                _status += "\nexception: " + e;
                NotifyLoaded();
            }
        }

        /// <summary>
        /// Callback for open completed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="openReadCompletedEventArgs"></param>
        void WebClientOpenReadCompleted(object sender, OpenReadCompletedEventArgs openReadCompletedEventArgs)
        {
            try
            {
                if (openReadCompletedEventArgs.Result != null)
                {
                    using (var streamReader = new StreamReader(openReadCompletedEventArgs.Result))
                    {
                        LoadFromStream(streamReader);
                    }
                    Sort();
                }
                else
                {
                    _status = "stream is null";
                }
            }
            catch (Exception ex)
            {
                _status += "\nexception: " + ex;
            }

            NotifyLoaded();
        }

        /// <summary>
        /// Parse the input steam into tournaments
        /// </summary>
        /// <param name="streamReader"></param>
        void LoadFromStream(TextReader streamReader)
        {
            try
            {
                if (streamReader != null)
                {
                    String line;
                    var firstLine = true;

                    while ((line = streamReader.ReadLine()) != null)
                    {
                        var fields = line.Split('\t');

                        if (fields.Length >= 8 && firstLine == false)
                        {
                            var tournamentModel = new TournamentModel
                                                      {
                                                          Name = fields[0].Trim(),
                                                          Course = fields[1].Trim(),
                                                          Location = fields[2].Trim().Replace("\"", ""),
                                                          From = DateTime.Parse(fields[3].Trim()),
                                                          To = DateTime.Parse(fields[4].Trim()),
                                                          Website = "http://" + fields[5].Trim(),
                                                          Season = fields[6].Trim(),
                                                          Weather = fields[7].Trim()
                                                      };
                            Add(tournamentModel);
                            _status = "loaded " + Count;
                        }

                        firstLine = false;
                    }

                    _status = "done";
                    _loaded = true;
                }
                else
                {
                    _status = "stream reader is null";
                }
            }
            catch (Exception e)
            {
                _status += "\nexception: " + e;
            }
        }

        /// <summary>
        /// Notification that the data was loaded
        /// </summary>
        void NotifyLoaded()
        {
            var tournamentsModelLoaded = TournamentsModelLoaded;

            if (tournamentsModelLoaded != null)
            {
                tournamentsModelLoaded.Invoke(this, new TournamentsModelLoadedEventArgs { Loaded = _loaded, Status = _status });
            }
        }

        /// <summary>
        /// Assign the results to this tournament that have the same play date, then sort the results
        /// </summary>
        /// <param name="resultsModel">Players and scores</param>
        public void AssignResults(ResultsModel resultsModel)
        {
            foreach (var tournamentModel in this)
            {
                var model = tournamentModel;
                foreach (var resultModel in
                    from resultModel in resultsModel
                    where resultModel.Date.CompareTo(model.From) == 0
                    select resultModel)
                {
                    resultModel.TournamentModel = tournamentModel;
                    tournamentModel.Results.Add(resultModel);
                }

                tournamentModel.Results.Sort();
            }
        }

        String _status;
        Boolean _loaded;
        WebClient _webClient;
    }

    public class TournamentsModelLoadedEventArgs : EventArgs
    {
        public Boolean Loaded { get; set; }
        public String Status { get; set; }
    }
}
